// tspcluster - Traveling Salesman Problem
// Copyright (C) 2006  Frederik Carlier
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
using System;
using System.IO;

namespace UGent.Tsp
{
    public class FlatBoltzmann
    {
        public FlatBoltzmann(MarkovCluster cluster)
        {
            this.cluster = cluster;
        }

        private MarkovCluster cluster;
        
        public void Run()
        {
            int run = 0;
            double beta = 0.0;

            // Create a flat distribution;
            Transitions transitions = new Transitions(cluster.HistogramNumberOfBins, cluster.HistogramLower, cluster.HistogramLowerExtended, cluster.HistogramUpper, cluster.HistogramUpperExtended);
            
            while (true)
            {
                run++;
                string fileName;

                Distribution distribution;
                
                if(transitions.Count == 0)
                    distribution = new Distribution(cluster.HistogramLower, cluster.HistogramLowerExtended, cluster.HistogramUpper, cluster.HistogramUpperExtended, cluster.HistogramNumberOfBins);
                else
                    distribution = transitions.GetDistribution(DistributionEstimator.TransitionMatrix);
                
                fileName = string.Format("run-{0}-distribution.txt", run);
                if(File.Exists(fileName))
                    File.Delete(fileName);
                
                using(FileStream stream = File.OpenWrite(fileName))
                {
                    distribution.WriteToStream(stream);
                }

                distribution = distribution.GetInverse();
                distribution.WeighExponential(beta);

                // Sample according to the inverse of the distribution
                cluster.SetAlgorithmType(AlgorithmType.MetropolisHastings);
                cluster.SetDistribution(distribution);

                cluster.Start();
                cluster.WaitForAll();

                Results results = cluster.GetResults();
                transitions.Merge(results.Transitions);
                
                Distribution histogram = results.Transitions.GetDistribution(DistributionEstimator.Histogram);
                // Write out a bunch of less or more interesting things.
                fileName = string.Format("run-{0}-histogram.txt", run);
                if(File.Exists(fileName))
                    File.Delete(fileName);
                
                using(FileStream stream = File.OpenWrite(fileName))
                {
                    histogram.WriteToStream(stream);
                }

                beta += 0.15;
            }
        }

        public static void RunOnConsole()
        {
            MarkovCluster cluster = new MarkovCluster();
            cluster.ConfigureOnConsole();
            cluster.ConfigureSimulationOnConsole();
            
            FlatBoltzmann boltzmann = new FlatBoltzmann(cluster);
            boltzmann.Run();
        }
    }
}
